﻿using System;
using System.Collections.Generic;
using System.Linq;
using Platformer_Example.Controller.Character;
using Platformer_Example.Controller.Character.Computer;
using Platformer_Example.Controller.Character.Computer.Monster;
using Platformer_Example.Controller.Character.Player;
using Platformer_Example.Controller.Data;
using Platformer_Example.Controller.Input;
using Platformer_Example.Controller.Map.Objects;
using Transformable_Engine_v2.Engine.Graphics;
using Transformable_Engine_v2.Engine.Transformable_Math.Geometry;

namespace Platformer_Example.Controller.Map
{
    /// <summary>
    /// Class used to contain all data relative to the current playing world map
    /// </summary>
    public class MapData
    {
        public Dictionary<string, Map> Maps { get; private set; }
        public string MapName { get; private set; }
        public Dictionary<Guid, Player> Players { get; private set; }
        public Dictionary<Guid, BaseComputer> Computers { get; private set; } 
        public Team[] Teams { get; private set; }
        private readonly Guid _localId;

        public Player LocalPlayer
        {
            get { return Players[_localId]; }
        }

        void AddMonster(BaseComputer monster, MapPlayerData monsterLocationData)
        {
            var mob = (BaseComputer)BaseCharacter.Create(monster);
            mob.ChangeMap(monsterLocationData.MapName, new CharacterPosition
            {
                Direction = monsterLocationData.NewPosition.Direction,
                Position = monsterLocationData.NewPosition.Position,
                State = monsterLocationData.NewPosition.State
            });
        }

        void AddPlayer(string playerId, MapPlayerData playerLocationData, Team team)
        {
            var character = (Player)BaseCharacter.Create(new Player(new InputState(), team));
            character.ChangeMap(playerLocationData.MapName, new CharacterPosition
            {
                Direction = playerLocationData.NewPosition.Direction,
                Position = playerLocationData.NewPosition.Position,
                State = playerLocationData.NewPosition.State
            });

            var id = Guid.Parse(playerId);
            Players.Add(id, character);
        }

        void AddObject(BasePickable obj, MapObjectData data)
        {
            obj.ChangeMap(data.MapName, data.NewPosition);
        }

        public MapData(Network.Messages.LoadGame mapData, Guid localId)
        {
            MapName = mapData.MapName;
            _localId = localId;

            Maps = new Dictionary<string, Map>();
            var maps = Map.FromDirectory(mapData.MapName);
            Maps = maps.ToDictionary(x => x.Id, x => x);
            Map.MapDictionary = Maps;

            Teams = new Team[mapData.Teams.Length];
            for (int i = 0; i < mapData.Teams.Length; i++)
            {
                Teams[i] = new Team(mapData.Teams[i].Name, mapData.Teams[i].ColorId);
            }

            var playerData = MapPlayerData.GetPlayerStartPositions(mapData.MapName);

            Players = new Dictionary<Guid, Player>();
            for (int i = 0; i < mapData.Players.Length; i++)
            {
                if (mapData.Players[i].Id != "Empty")
                {
                    AddPlayer(mapData.Players[i].Id, playerData[i], mapData.Teams[i / (mapData.Players.Length / mapData.Teams.Length)]);
                }
            }

            Computers = new Dictionary<Guid, BaseComputer>();

            #warning Read monster data from a file
            Team monstersTeam = new Team("Monsters", -1);
            //AddMonster(new Test(monstersTeam), new MapPlayerData("Test0", new TE_Vector2(13.5f, 20), BaseInputCharacter.State.Fall, BaseInputCharacter.Direction.Right));
            //AddMonster(new Test(monstersTeam), new MapPlayerData("Test0", new TE_Vector2(15.5f, 20), BaseInputCharacter.State.Fall, BaseInputCharacter.Direction.Right));
            //AddMonster(new Test(monstersTeam), new MapPlayerData("Test0", new TE_Vector2(17.5f, 20), BaseInputCharacter.State.Fall, BaseInputCharacter.Direction.Right));

            #warning Read object data from a file
            AddObject(new BoxPickup(), new MapObjectData("Test0", new TE_Vector2(26, 10)));
            AddObject(new BoxPickup(), new MapObjectData("Test0", new TE_Vector2(5, 12)));
        }
    }
}